/**********************************
 * 存放最核心的数据结构:
 * 1.用户信息
 * 2.会话信息
 * 3.消息信息
 * 4.工具函数
 *********************************/
#pragma once
#include <QString>
#include <QIcon>
#include <QByteArray>
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QString>
#include <QFileInfo>

#include "base.qpb.h"
#include "gateway.qpb.h"


namespace model
{
    /***********************************************
     * 一些工具函数
     ***********************************************
     */
    static inline QString GetFileName(const QString filePath)
    {
        QFileInfo fileinfo(filePath);
        return fileinfo.fileName();
    }

    //日志的宏函数
    #define TAG QString("[%1:%2]").arg(model::GetFileName(__FILE__),QString::number(__LINE__))
    #define LOG() qDebug().noquote() << TAG

    //产生唯一ID
    static inline QString makeId()
    {
        return  "M" + QUuid::createUuid().toString().sliced(25,12);    //仅取部分
    }

    //格式化好的时间
    static inline QString formatTime(int64_t timestamp)
    {
        QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp);
        return datetime.toString("yyyy-MM-dd HH:mm:ss");
    }

    //获取时间戳
    static inline int64_t getTime()
    {
        return QDateTime::currentSecsSinceEpoch();
    }

    //文件读写
    static inline QByteArray loadFile2ByteArray(QString filePath)
    {
        QFile file(filePath);
        if(!file.open(QFile::ReadOnly))
        {
            LOG() << "读文件打开失败";
            return QByteArray();
        }
        QByteArray content = file.readAll();
        file.close();//别忘记关闭文件
        return content;
    }

    static inline void writeByteArray2File(QString filePath,const QByteArray content)
    {
        QFile file(filePath);
        if(!file.open(QFile::WriteOnly))
        {
            LOG() << "写文件打开失败";
            return;
        }
        file.write(content);
        file.flush();
        file.close();
    }


    //QByteArray 转 QIcon
    static inline QIcon QByteArray2QIcon(const QByteArray& byteArray)
    {
        QPixmap pixmap;
        pixmap.loadFromData(byteArray);
        QIcon icon(pixmap);
        return icon;
    }


    /***********************************************
     * 用户信息
     ***********************************************
     */
    class UserInfo
    {
    public:
        QString userId = "";         //用户ID
        QString nickName = "";       //用户昵称
        QString description = "";    //个性签名
        QString phoneNumber = "";    //手机号码
        QIcon avatar;           //用户头像

        //从protobuf中的UserInfo对象，转成当前代码的UserInfo对象
        void load(const my::UserInfo& userInfo)
        {
            this->userId = userInfo.userId();
            this->nickName = userInfo.nickname();
            this->description = userInfo.description();
            this->phoneNumber = userInfo.phone();
            if(userInfo.avatar().isEmpty())
            {
                this->avatar = QIcon(":/resource/lion.png");
            }
            else
            {
                this->avatar = model::QByteArray2QIcon(userInfo.avatar());
            }
        }
    };

    /***********************************************
     * 消息信息
     ***********************************************
     */

    enum MessageType
    {
        TEXT_TYPE,      //文本
        FILE_TYPE,      //文件
        IMAGE_TYPE,     //图片
        SPEECH_TYPE,    //语音
    };

    class MessageInfo
    {
    public:
        QString messageId = "";     //消息ID
        QString sessionId = "";     //所属会话ID
        QString time = "";          //消息时间
        MessageType messageType;    //消息类型
        UserInfo userInfo;          //发送者信息
        QByteArray content;         //消息内容

        //以下两项，针对文件类型是文件、图片、语音时使用；文本类型默认为空
        QString fileId = "";        //文件标识符
        //针对文件类型时使用
        QString fileName = "";      //文件名称

        void load(const my::MessageInfo& messageInfo)
        {
            this->messageId = messageInfo.messageId();
            this->sessionId = messageInfo.chatSessionId();
            this->time = model::formatTime(messageInfo.timestamp());
            this->userInfo.load(messageInfo.sender());

            //根据类型，设置内容与文件Id
            my::MessageTypeGadget::MessageType messageType = messageInfo.message().messageType();
            if(messageType == my::MessageTypeGadget::MessageType::STRING)
            {
                this->messageType = model::MessageType::TEXT_TYPE;
                this->content = messageInfo.message().stringMessage().content().toUtf8();
            }
            else if(messageType == my::MessageTypeGadget::MessageType::FILE)
            {
                this->messageType = model::MessageType::FILE_TYPE;
                if(messageInfo.message().fileMessage().hasFileContents())
                {
                    this->content = messageInfo.message().fileMessage().fileContents();
                }

                if(messageInfo.message().fileMessage().hasFileId())
                {
                    this->fileId = messageInfo.message().fileMessage().fileId();
                }
                this->fileName = messageInfo.message().fileMessage().fileName();
            }
            else if(messageType == my::MessageTypeGadget::MessageType::IMAGE)
            {
                this->messageType = model::MessageType::IMAGE_TYPE;
                if(messageInfo.message().imageMessage().hasImageContent())
                {
                    this->content = messageInfo.message().imageMessage().imageContent();
                }

                if(messageInfo.message().imageMessage().hasFileId())
                {
                    this->fileId = messageInfo.message().imageMessage().fileId();
                }
            }
            else if(messageType == my::MessageTypeGadget::MessageType::SPEECH)
            {
                this->messageType = model::SPEECH_TYPE;
                if(messageInfo.message().speechMessage().hasFileContents())
                {
                    this->content = messageInfo.message().speechMessage().fileContents();
                }

                if(messageInfo.message().speechMessage().hasFileId())
                {
                    this->fileId = messageInfo.message().speechMessage().fileId();
                }
            }
            else
            {
                LOG() << "错误的消息类型,messageType:" <<  messageType;
            }

        }

        //生成messageInfo的工厂方法
        static MessageInfo makeMessage(const model::MessageType messageType,
                                       const QString sessionID,
                                       const model::UserInfo sender,
                                       const QByteArray content,
                                       const QString extraInfo)
        {
            switch (messageType)
            {
            case model::MessageType::TEXT_TYPE:
                return makeTextMessage(sessionID,sender,content);
            case model::MessageType::FILE_TYPE:
                return makeFileMessage(sessionID,sender,content,extraInfo);
            case model::MessageType::IMAGE_TYPE:
                return makeImageMessage(sessionID,sender,content);
            case model::MessageType::SPEECH_TYPE:
                return makeSpeechMessage(sessionID,sender,content);
            default:
                return MessageInfo();
            }
        }
    private:
        //产生不同类型的MessageInfo
        static MessageInfo makeTextMessage(const QString& sessionId, const UserInfo& sender, const QByteArray& content)
        {
            MessageInfo message;
            message.messageType = model::MessageType::TEXT_TYPE;
            message.messageId = makeId();
            message.sessionId = sessionId;
            message.userInfo = sender;
            message.content = content;
            message.time = formatTime(getTime());
            return message;
        }
        static MessageInfo makeFileMessage(const QString& sessionId,
                                           const UserInfo& sender,
                                           const QByteArray& content,
                                           const QString& fileName)
        {
            MessageInfo message;
            message.messageType = model::MessageType::FILE_TYPE;
            message.messageId = makeId();
            message.sessionId = sessionId;
            message.userInfo = sender;
            message.content = content;
            message.time = formatTime(getTime());
            message.fileName = fileName;
            LOG() << "fileName = " << fileName << " 文件内容 = " << content;
            return message;
        }
        static MessageInfo makeImageMessage(const QString& sessionId, const UserInfo& sender, const QByteArray& content)
        {
            MessageInfo message;
            message.messageType = model::MessageType::IMAGE_TYPE;
            message.messageId = makeId();
            message.sessionId = sessionId;
            message.userInfo = sender;
            message.content = content;
            message.time = formatTime(getTime());
            return message;
        }
        static MessageInfo makeSpeechMessage(const QString& sessionId, const UserInfo& sender, const QByteArray& content)
        {
            MessageInfo message;
            message.messageType = model::MessageType::SPEECH_TYPE;
            message.messageId = makeId();
            message.sessionId = sessionId;
            message.userInfo = sender;
            message.content = content;
            message.time = formatTime(getTime());
            // message.fileId = "";
            // message.fileName = "";
            return message;
        }
    };


    /***********************************************
     * 会话信息
     ***********************************************
     */
    class ChatSessionInfo
    {
    public:
        QString sessionId = "";          //会话
        QString sessionName = "";        //会话名称
        MessageInfo prevMessage;    //当前会话过去最新的消息
        QIcon avatar;               //会话头像
        QString userId = "";        //单聊是用户ID,对于群聊是""

        void load(const my::ChatSessionInfo& chatSessionInfo)
        {
            this->sessionId = chatSessionInfo.chatSessionId();
            this->sessionName = chatSessionInfo.chatSessionName();
            if(chatSessionInfo.hasSingleChatFriendId())
            {
                this->userId = chatSessionInfo.singleChatFriendId();
            }

            if(chatSessionInfo.hasPrevMessage())
            {
                this->prevMessage.load(chatSessionInfo.prevMessage());
            }

            if(chatSessionInfo.hasAvatar() && !chatSessionInfo.avatar().isEmpty())
            {
                this->avatar = model::QByteArray2QIcon(chatSessionInfo.avatar());
            }
            else
            {
                // 如果没有头像, 则根据当前会话是单聊还是群聊, 使用不同的默认头像.
                if(this->userId != "")
                {
                    //单聊
                    this->avatar = QIcon(":/resource/lion.png");
                }
                else
                {
                    //群聊
                    this->avatar = QIcon(":/resource/SessionDetail.png");
                }
            }
        }

    };

} //model_data
